/**
 * Copyright &copy; 2012-2014 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.thinkgem.jeesite.modules.employee.service;

import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.service.CrudService;
import com.thinkgem.jeesite.common.utils.CalendarUtils;
import com.thinkgem.jeesite.common.utils.Constons;
import com.thinkgem.jeesite.common.utils.DateUtils;
import com.thinkgem.jeesite.common.utils.IdGen;
import com.thinkgem.jeesite.modules.cn.dao.AttendanceCnDao;
import com.thinkgem.jeesite.modules.cn.entity.AttendanceCn;
import com.thinkgem.jeesite.modules.employee.dao.AttendanceRecordsDao;
import com.thinkgem.jeesite.modules.employee.dao.EmployeeLeaveDao;
import com.thinkgem.jeesite.modules.employee.entity.AttendanceRecords;
import com.thinkgem.jeesite.modules.employee.entity.Checkinout;
import com.thinkgem.jeesite.modules.employee.entity.Employee;
import com.thinkgem.jeesite.modules.employee.entity.EmployeeLeave;
import com.thinkgem.jeesite.modules.employee.entity.StatutoryHolidays;
import com.thinkgem.jeesite.modules.schedul.entity.Schclass;
import com.thinkgem.jeesite.modules.schedul.entity.SchedulingInformation;
import com.thinkgem.jeesite.modules.schedul.service.SchclassService;
import com.thinkgem.jeesite.modules.schedul.service.SchedulingInformationService;
import com.thinkgem.jeesite.modules.shift.entity.Shift;
import com.thinkgem.jeesite.modules.shift.service.ShiftService;
import com.thinkgem.jeesite.modules.sys.entity.Office;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.us.dao.UsAttendanceAdpDao;

/**
 * 考勤结果统计Service
 * @author pan.zhou
 * @version 2017-07-21
 */
@Service
@Transactional(readOnly = true)
public class AttendanceRecordsService extends CrudService<AttendanceRecordsDao, AttendanceRecords> {
	@Autowired
	private CheckinoutService checkinoutService;
	@Autowired
	private SchedulingInformationService schedulingInformationService;
	@Autowired
	private ShiftService shiftService;
	@Autowired
	private SchclassService schclassService;
	@Autowired
	private EmployeeLeaveService employeeLeaveService;
	@Autowired
	private EmployeeService employeeService;
	@Autowired
	private StatutoryHolidaysService statutoryHolidaysService;
	@Autowired
    private  UsAttendanceAdpDao usAttendanceAdpDao;
	@Autowired
    private  AttendanceCnDao attendanceCnDao;
	@Autowired
    private  EmployeeLeaveDao employeeLeaveDao;
	

	public AttendanceRecords get(String id) {
		return super.get(id);
	}
	
	public List<AttendanceRecords> findList(AttendanceRecords attendanceRecords) {
		return super.findList(attendanceRecords);
	}
	
	public Page<AttendanceRecords> findPage(Page<AttendanceRecords> page, AttendanceRecords attendanceRecords) {
		return super.findPage(page, attendanceRecords);
	}
	
	@Transactional(readOnly = false)
	public void save(AttendanceRecords attendanceRecords) {
		super.save(attendanceRecords);
	}
	
	@Transactional(readOnly = false)
	public void delete(AttendanceRecords attendanceRecords) {
		super.delete(attendanceRecords);
	}

	/**
	 * 根据用户的打卡记录，计算出当天用户考勤
	 * @param employeeNumer 用户编码
	 * @param today 打卡日期 精确到日就可以了
	 */
	@Transactional(readOnly = false)
	public void genelUserAttendanceRecordsByCheckinout(String employeeNumer, Date today) {

		boolean needSetCoffiece = false;
		AttendanceRecords attendanceRecords = new AttendanceRecords(employeeNumer, today, Constons.DELETE_N);
		List<AttendanceRecords> attendanceRecordsList = super.findList(attendanceRecords);
		if (null != attendanceRecordsList && !attendanceRecordsList.isEmpty()) {
			attendanceRecords = attendanceRecordsList.get(0);
			attendanceRecords.preUpdate();
		} else {
			attendanceRecords.setIsNewRecord(true);
			attendanceRecords.preInsert();
			attendanceRecords.setId(IdGen.uuid());
			needSetCoffiece = true;
		}
		Employee employee = employeeService.findOneByEmployeeNumer(employeeNumer);
		User user = new User();
		user.setId("1");

		attendanceRecords.setCreateBy(user);
		attendanceRecords.setUpdateBy(user);
		attendanceRecords.setCreateDate(new Date());
		attendanceRecords.setUpdateDate(new Date());

		if(needSetCoffiece){
			attendanceRecords.setCompany(employee.getCompany());
			attendanceRecords.setOffice(employee.getOffice());

		}
		attendanceRecords.setName(employee.getName());

		double workTime = 0.00;//工时
		double freeTime = 0.00;//休息时间
		double holidayTime = 0.00;//假期
		String isAbsent = Constons.N;
		String chidao = Constons.Y;
		String isEx =Constons.N;
		String isZaoTui = Constons.Y;//是否早退


			//获取用户排班计划
			SchedulingInformation schedulingInformation = new SchedulingInformation(employeeNumer, today, today, Constons.DELETE_N);
			List<SchedulingInformation> schedulingInformationList = schedulingInformationService.findList(schedulingInformation);
			//根据排班获取班次
			List<Shift> shiftList = shiftService.findAllByEmployeeNumerAndDate(schedulingInformationList, DateUtils.getWeekByDate(today));
			//根据班次获取考勤时段，根据时段计算
			for (Shift one : shiftList) {
			Schclass schclass = schclassService.get(one.getSchclass().getId());
            String todatStr = CalendarUtils.formatDate(today);// 变成yyyy-mm-dd
            // 统计工时
            Date alldkStarTime = schclass.getCheckintime1();//
            Date alldkEndTime = schclass.getCheckouttime2();//
            List<Checkinout> alldaCheckinoutList = checkinoutService.findListByeMployeeNumerAndDate(todatStr,
                employeeNumer,
                alldkStarTime,
                alldkEndTime);
            Collections.sort(alldaCheckinoutList, new Comparator<Checkinout>() {
					public int compare(Checkinout o1, Checkinout o2) {
						return CalendarUtils.millisBetween(o1.getChecktime(), o2.getChecktime());
					}
				});
            //alldaCheckinoutList.sort((a, b) -> CalendarUtils.millisBetween(a.getChecktime(), b.getChecktime()));
            // 没有考勤记录
            if (null == alldaCheckinoutList || alldaCheckinoutList.isEmpty()) {
                // 无打卡记录，去休假表里找是否有休假记录
                EmployeeLeave employeeLeave = new EmployeeLeave(employeeNumer, today, today, Constons.DELETE_N);
                List<EmployeeLeave> employeeLeaveList = employeeLeaveService.findList(employeeLeave);
                chidao = Constons.N;
                isZaoTui = Constons.N;
                if (null == employeeLeaveList || employeeLeaveList.isEmpty()) {
                    // 旷工
                    isAbsent = Constons.Y;
                } else {
                    isAbsent = Constons.N;
                    // 事假
                    for (EmployeeLeave leave : employeeLeaveList) {
                        holidayTime += Double.valueOf(leave.getLeaveTime());
                    }
                }

            } else if (alldaCheckinoutList.size() % 2 != 0&&alldaCheckinoutList.size()>0) {
                isAbsent = Constons.N;
				isZaoTui = Constons.N;//早退
                chidao = Constons.N;//迟到
                isEx = Constons.Y;
                workTime = 0.00;// 工时
                freeTime = 0.00;// 休息时间
                holidayTime = 0.00;// 假期
            } else {

                // 先判断是否在上班时间打过卡，如果有则是否
                Date sbdkStarTime = schclass.getCheckintime1();// 上班打卡时间
                Date sbdkendTime = CalendarUtils.addMinutes(schclass.getStarttime(),5);//延迟五分钟

                List<Checkinout> sbdkCheckinoutList = checkinoutService.findListByeMployeeNumerAndDate(todatStr,
                    employeeNumer,
                    sbdkStarTime,
                    sbdkendTime);
                if (null == sbdkCheckinoutList || sbdkCheckinoutList.isEmpty()) {
                    chidao = Constons.Y;
                } else {
                    chidao = Constons.N;
                }

                // 判断是否早退
                Date xbdkStarTime = schclass.getCheckouttime1();//
                Date xbdkEndTime = schclass.getCheckouttime2();//

                List<Checkinout> xbdaCheckinoutList = checkinoutService.findListByeMployeeNumerAndDate(todatStr,
                    employeeNumer,
                    xbdkStarTime,
                    xbdkEndTime);
				if (null == xbdaCheckinoutList || xbdaCheckinoutList.isEmpty()) {
					isZaoTui = Constons.Y;
				} else {
					isZaoTui = Constons.N;
				}


				//法定节假日
				StatutoryHolidays statutoryHolidays = new StatutoryHolidays();
				statutoryHolidays.setCompany(employee.getCompany());
				statutoryHolidays.setDelFlag(Constons.DELETE_N);
				statutoryHolidays.setDate(today);
				List<StatutoryHolidays> statutoryHolidaysList = statutoryHolidaysService.findList(statutoryHolidays);
				for (StatutoryHolidays holidays : statutoryHolidaysList) {
					holidayTime += 8.0;
				}

					int listSize = alldaCheckinoutList.size();
				int index = 0;
						for (int i = 1; i <= listSize; i++) {
                    if (i % 2 == 0) {
                    	index++;
                        workTime += CalendarUtils.diffMinute(alldaCheckinoutList.get(i - 1).getChecktime(),
                            alldaCheckinoutList.get(i - 2).getChecktime());
							}
                    if ((i % (2*index+1) == 0)&&i>2) {
                        freeTime += CalendarUtils.diffMinute(alldaCheckinoutList.get(i - 1).getChecktime(),
                            alldaCheckinoutList.get(i - 2).getChecktime());
							}

						}
						workTime = workTime / 60;
						freeTime = freeTime / 60;

				}
				attendanceRecords.setShiftId(one.getId());
		workTime = workTime-workTime%0.25;
		attendanceRecords.setIsException(isEx);
		attendanceRecords.setWorkHour(String.valueOf(workTime));
		attendanceRecords.setIsAbsent(isAbsent);
		attendanceRecords.setIsLate(chidao);
		attendanceRecords.setIsEarlyLeave(isZaoTui);
		if(workTime<6&&0<freeTime&& freeTime<0.5){
			freeTime = 0.5;
		}
		attendanceRecords.setResetHour(String.valueOf(freeTime));
		attendanceRecords.setHolidayHour(String.valueOf(holidayTime));

		super.save(attendanceRecords);
	}

	}
    public Page<AttendanceRecords> queryExceptionEmployee(Page<AttendanceRecords> page,
                                                          AttendanceRecords attendanceRecords) {
        attendanceRecords.setPage(page);
        page.setList(dao.queryExceptionEmployee(attendanceRecords));
        return page;
    }

	/**
	 * 根据仓库和日期查询,员工类型查询，
	 * @param date
	 * @param ukle
	 * @return
	 */
	public List<AttendanceRecords> queryAllByOutSourceEmloee(Date date, Constons.WarehouseType ukle,String userType) {
		return dao.queryAllByOutSourceEmloee(date,ukle.name(),userType);
	}

	public double queryTotalWeekByOutSourceEmloeeAndWeek(Date monday, Date date, String number) {
		return dao.queryTotalWeekByOutSourceEmloeeAndWeek(monday,date,number);
	}

	/**
	 * 
	 * 计算美东仓考勤
	 * @param uskynList
	 */
	@Transactional
    public void generateAllAttendance(List<AttendanceCn> uskynList) {
        if(uskynList!=null&&uskynList.size()>0){
            for (AttendanceCn attendance : uskynList) {
                try {
                    AttendanceRecords attendanceRecords = new AttendanceRecords();
                    attendanceRecords.setAttendanceDate(attendance.getDate());
                    if (StringUtils.isBlank(attendance.getNumber())) {
                        attendanceRecords.setEmployeenumber("EXCEPTION");
                        attendanceRecords.setIsException("Y");
                    } else {
                        attendanceRecords.setEmployeenumber(attendance.getNumber());
                        attendanceRecords.setIsException("N");
                    }
                    attendanceRecords.setIsAbsent("N");
                    attendanceRecords.setIsEarlyLeave("N");
                    attendanceRecords.setIsLate("N");
                    attendanceRecords.setHolidayHour("0");
                    attendanceRecords.setResetHour("0");
                    attendanceRecords.setWorkHour(attendance.getWorkingHours());
                    attendanceRecords.setName(attendance.getEmployee());
                    attendanceRecords.setCompany(new Office(attendance.getCompanyId()));
                    attendanceRecords.setOffice(new Office(attendance.getOfficeId()));
                    super.save(attendanceRecords);
                    
                    if (StringUtils.isBlank(attendance.getNumber())) {
                        usAttendanceAdpDao.updateByEmployeeDate(attendance.getNumber(),attendance.getDate());
                        attendanceCnDao.updateByEmployeeDate(attendance.getNumber(),attendance.getDate());
                    }
                    
                } catch (Exception e) {
                    logger.error("工时对接 异常,员工编号：{},仓库：{},异常：{}",attendance.getNumber(),attendance.getOfficeId(),e.getMessage());
                }
            }          
        }     
    }
	/**
	 * 
	 * 根据法定节假日和请假生成考勤
	 */
    public void generateLeaveAttendance() {
        //处理普通请假类型
        List<EmployeeLeave> employeeLeaves = employeeLeaveDao.queryWithoutUK();
        for (EmployeeLeave employeeLeave : employeeLeaves) {
            AttendanceRecords attendanceRecords = new AttendanceRecords();
            attendanceRecords.setAttendanceDate(employeeLeave.getApplicationDate());
            attendanceRecords.setEmployeenumber(employeeLeave.getEmployeeNumber());
            attendanceRecords.setIsException("N");
            attendanceRecords.setIsAbsent("N");
            attendanceRecords.setIsEarlyLeave("N");
            attendanceRecords.setIsLate("N");
            attendanceRecords.setHolidayHour(employeeLeave.getLeaveTime());
            attendanceRecords.setResetHour("0");
            attendanceRecords.setWorkHour("0");
            attendanceRecords.setName(employeeLeave.getEmployeeName());
            attendanceRecords.setCompany(new Office(employeeLeave.getCompanyId()));
            attendanceRecords.setOffice(new Office(employeeLeave.getOfficeId()));
            super.save(attendanceRecords);
            employeeLeave.setIsCalculate("2");     
            employeeLeaveDao.update(employeeLeave);                
        }
        
    }
}